1use crate::ext::io::*;
2use crate::types::*;
3use crate::utils::encoding::*;
4use anyhow::Result;
5use serde::{Deserialize, Serialize};
6use std::io::{Read, Seek, SeekFrom};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9enum Oper {
10 B,
12 W,
14 D,
16 S,
18 F,
20}
21
22use Oper::*;
23
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25#[serde(tag = "t", content = "c")]
26pub enum Operand {
27 B(u8),
28 W(u16),
29 D(u32),
30 S(String),
31 F(f32),
32}
33
34impl Operand {
35 pub fn len(&self, encoding: Encoding) -> Result<usize> {
36 Ok(match self {
37 Operand::B(_) => 1,
38 Operand::W(_) => 2,
39 Operand::D(_) => 4,
40 Operand::S(s) => {
41 let bytes = encode_string(encoding, s, true)?;
42 bytes.len() + 2
44 }
45 Operand::F(_) => 4,
46 })
47 }
48}
49
50const OPS: [(u8, &[Oper]); 49] = [
51 (0x00, &[]), (0x01, &[B, B]), (0x02, &[D]), (0x03, &[W]), (0x04, &[]), (0x05, &[]), (0x06, &[D]), (0x07, &[D]), (0x08, &[]), (0x09, &[]), (0x0a, &[D]), (0x0b, &[W]), (0x0c, &[B]), (0x0d, &[F]), (0x0e, &[S]), (0x0f, &[W]), (0x10, &[B]), (0x11, &[W]), (0x12, &[B]), (0x13, &[]), (0x14, &[]), (0x15, &[W]), (0x16, &[B]), (0x17, &[W]), (0x18, &[B]), (0x19, &[]), (0x1a, &[]), (0x1b, &[]), (0x1c, &[]), (0x1d, &[]), (0x1e, &[]), (0x1f, &[]), (0x20, &[]), (0x21, &[]), (0x22, &[]), (0x23, &[]), (0x24, &[]), (0x25, &[]), (0x26, &[]), (0x27, &[]), (0x33, &[]),
92 (0x3f, &[]),
93 (0x40, &[]),
94 (0xb3, &[]),
95 (0xb8, &[]),
96 (0xd8, &[]),
97 (0xf0, &[]),
98 (0x52, &[]),
99 (0x9e, &[]),
100];
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct Func {
104 pub pos: u64,
105 pub opcode: u8,
106 pub operands: Vec<Operand>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct Data {
111 pub functions: Vec<Func>,
112 pub main_script: Vec<Func>,
113 pub extra_data: Vec<u8>,
114}
115
116impl Data {
117 pub fn disasm<R: Read + Seek>(mut reader: R, encoding: Encoding) -> Result<Self> {
118 let mut data = Data {
119 functions: Vec::new(),
120 main_script: Vec::new(),
121 extra_data: Vec::new(),
122 };
123 let script_len = reader.read_u32()? as u64;
124 let main_script_data = reader.peek_u32_at(script_len)? as u64;
125 {
126 let mut target = &mut data.functions;
127 let mut pos = reader.stream_position()?;
128 while pos < script_len {
129 if pos >= main_script_data {
130 target = &mut data.main_script;
131 }
132 target.push(Self::read_func(&mut reader, encoding)?);
133 pos = reader.stream_position()?;
134 }
135 }
136 reader.seek(SeekFrom::Start(script_len + 4))?;
137 reader.read_to_end(&mut data.extra_data)?;
138 Ok(data)
139 }
140
141 fn read_func<R: Read + Seek>(reader: &mut R, encoding: Encoding) -> Result<Func> {
142 let pos = reader.stream_position()?;
143 let opcode = reader.read_u8()?;
144 let operands = if let Some((_, ops)) = OPS.iter().find(|(code, _)| *code == opcode) {
145 let mut operands = Vec::with_capacity(ops.len());
146 for &op in *ops {
147 let operand = match op {
148 B => Operand::B(reader.read_u8()?),
149 W => Operand::W(reader.read_u16()?),
150 D => Operand::D(reader.read_u32()?),
151 S => {
152 let len = reader.read_u8()? as usize;
153 let s = reader.read_cstring()?;
154 if s.as_bytes_with_nul().len() != len {
155 return Err(anyhow::anyhow!(
156 "String length mismatch at {:#x}: expected {}, got {}",
157 pos,
158 len,
159 s.as_bytes_with_nul().len()
160 ));
161 }
162 let s = decode_to_string(encoding, s.as_bytes(), true)?;
163 Operand::S(s)
164 }
165 F => Operand::F(reader.read_f32()?),
166 };
167 operands.push(operand);
168 }
169 operands
170 } else {
171 return Err(anyhow::anyhow!(
172 "Unknown opcode: {:#x} at {:#x}",
173 opcode,
174 pos
175 ));
176 };
177 Ok(Func {
178 pos,
179 opcode,
180 operands,
181 })
182 }
183}